from django.shortcuts import render,redirect,get_object_or_404,HttpResponse
from django.db.models import Q
from ..models import Device,DevBackups

from django.utils.safestring import mark_safe
from ..utlis import fenyezujian

import os

from netmiko import ConnectHandler
import threading
from queue import Queue
import time
from datetime import datetime


def backup(request):
    if request.method == 'GET':
        #实现搜索功能,定义一个空字典
        data_dict = {}
        #通过前端传递过来的q参数获取数据，如果不为空，则将搜索的数据放入到字典中
        search_data = request.GET.get("q","")
        q1=Q()
        if search_data:
            # #在数据库中查询IP的搜索语句
            # data_dict["ip_address__contains"] = search_data

            q1.connector = 'OR'
            q1.children.append(('ip', search_data))
            q1.children.append(('diqu', search_data))

            # 定义当前页,通过前端传递过来的page参数获取当前页码，在HTML中定义的name属性字段
            page = int(request.GET.get('page', 1))

            # 定义页码显示多少条数据
            page_size = 1

            # 定义每页开始位置
            start = (page - 1) * page_size

            # 定义每页结束位置
            end = page * page_size

            # 从数据库查询数据，加上筛选条件，如果进行了搜索数据会添加到data_dict字段中，如果没有则查询全部数据；[start:end]显示数据多少条
            device = Device.objects.filter(q1)[start:end]

            # 计算出总数据
            total_count = Device.objects.filter(q1).count()

            # 计算出总页码;总页数/单页显示的数据   div是python自带的计算工具
            total_page_count, div = divmod(total_count, page_size)
            if div:
                total_page_count += 1

            # 计算出 显示当前页的前后5页
            plus = 5

            if total_page_count <= 2 * plus + 1:
                # 当数据库中数据量少时，小于11页
                start_page = 1  # 开始页=1
                end_page = total_page_count  # 结束也=当前总页码
            else:
                # 当前页码<5时
                if page <= plus:
                    start_page = 1
                    end_page = 2 * plus + 1
                else:
                    # 当前页码 + 要显示的页码 > 总页码时
                    if (page + plus) > total_page_count:
                        start_page = total_page_count - 2 * plus
                        end_page = total_page_count
                    else:
                        start_page = page - plus
                        end_page = page + plus

            # 页码
            page_str_list = []

            # 首页
            page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))

            # 上一页，如果当前页大于1，则-1，如果当前页就是1则还显示当前页
            if page > 1:
                prev = '<li><a href="?page={}">上一页</a></li>'.format(page - 1)
            else:
                prev = '<li><a href="?page={}">上一页</a></li>'.format(1)
            page_str_list.append(prev)

            # for循环，生成开始页和结束页
            for i in range(start_page, end_page + 1):
                # 如果i=当前页，在前端加个样式，如果不等于当前页则不添加
                if i == page:
                    ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
                else:
                    ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)
                # 将生成出来的页码写入到列表中
                page_str_list.append(ele)

            # 下一页
            if page < total_page_count:
                prev = '<li><a href="?page={}">下一页</a></li>'.format(page + 1)
            else:
                prev = '<li><a href="?page={}">下一页</a></li>'.format(total_page_count)
            page_str_list.append(prev)

            # 尾页
            page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(total_page_count))

            page_string = mark_safe("".join(page_str_list))

            return render(request, "backups.html", {"devices": device, "page_string": page_string,"search_data":search_data})

        else:
            #定义当前页,通过前端传递过来的page参数获取当前页码，在HTML中定义的name属性字段
            page = int(request.GET.get('page',1))

            #定义页码显示多少条数据
            page_size = 10

            #定义每页开始位置
            start = (page -1)* page_size

            #定义每页结束位置
            end = page * page_size

            #从数据库查询数据，加上筛选条件，如果进行了搜索数据会添加到data_dict字段中，如果没有则查询全部数据；[start:end]显示数据多少条
            devices = Device.objects.filter(**data_dict)[start:end]

            #计算出总数据
            total_count = Device.objects.filter(**data_dict).count()

            #计算出总页码;总页数/单页显示的数据   div是python自带的计算工具
            total_page_count,div = divmod(total_count,page_size)
            if div:
                total_page_count +=1

            #计算出 显示当前页的前后5页
            plus = 5

            if total_page_count <= 2 * plus + 1:
                # 当数据库中数据量少时，小于11页
                start_page = 1  # 开始页=1
                end_page = total_page_count  # 结束也=当前总页码
            else:
                # 当前页码<5时
                if page <= plus:
                    start_page = 1
                    end_page = 2 * plus + 1
                else:
                    # 当前页码 + 要显示的页码 > 总页码时
                    if (page + plus) > total_page_count:
                        start_page = total_page_count - 2 * plus
                        end_page = total_page_count
                    else:
                        start_page = page - plus
                        end_page = page + plus

            #页码
            page_str_list = []

            # 首页
            page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))

            # 上一页，如果当前页大于1，则-1，如果当前页就是1则还显示当前页
            if page > 1:
                prev = '<li><a href="?page={}">上一页</a></li>'.format(page - 1)
            else:
                prev = '<li><a href="?page={}">上一页</a></li>'.format(1)
            page_str_list.append(prev)

            # for循环，生成开始页和结束页
            for i in range(start_page, end_page + 1):
                # 如果i=当前页，在前端加个样式，如果不等于当前页则不添加
                if i == page:
                    ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
                else:
                    ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)
                # 将生成出来的页码写入到列表中
                page_str_list.append(ele)

            # 下一页
            if page < total_page_count:
                prev = '<li><a href="?page={}">下一页</a></li>'.format(page + 1)
            else:
                prev = '<li><a href="?page={}">下一页</a></li>'.format(total_page_count)
            page_str_list.append(prev)

            # 尾页
            page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(total_page_count))

            page_string = mark_safe("".join(page_str_list))

            return render(request, "backups.html", {"devices": devices, "page_string": page_string})

    elif request.method == 'POST':
        now = time.strftime("%Y-%m-%d")
        now1 = datetime.now()
        date = f'{now1.month}_{now1.day}_{now1.year}'
        result= []
        selected_device_id = request.POST.getlist('device')

        search_data = request.GET.get("q", "")
        q1 = Q()
        if search_data:
            # #在数据库中查询IP的搜索语句
            # data_dict["ip_address__contains"] = search_data

            q1.connector = 'OR'
            q1.children.append(('ip', search_data))
            q1.children.append(('diqu', search_data))
        if not selected_device_id:
            devices = Device.objects.filter(q1).all()
            for i in devices:
                selected_device_id.append(i.id)
        for x in selected_device_id:
            try:
                if not x:
                    continue
                dev = get_object_or_404(Device,pk=x)

                #判断设备类型
                if dev.vendor.lower() == 'cisco':
                    def session1(ip,output):
                        conn = ConnectHandler(**sw)
                        output = conn.send_config_from_file("net_dev/command/cisco_comm.txt")

                        #定义备份路径
                        with open("net_dev/command/backup/"+ dev.dev_name + "_" + date + ".txt",'a') as f:
                            f.write(output)

                        data_dic = {
                            "title": dev.dev_name + "_" + date + ".txt",
                            "time": now,
                            "ip": ip
                        }
                        DevBackups.objects.create(**data_dic)

                    ip1 = []
                    ip1.append(dev.ip)
                    for ip in ip1:
                        sw = {'device_type': "cisco_ios", 'ip': ip, 'username': dev.username, 'password': dev.password}
                        t = threading.Thread(target=session1, args=(ip, Queue()))
                        t.start()
                        time.sleep(5)
                        result.append(f'{ip}配置备份成功!')

                elif dev.vendor.lower() == 'huawei':
                    def session2(ip,output):
                        conn = ConnectHandler(**sw)
                        output = conn.send_config_from_file('net_dev/command/hw_comm.txt')
                        with open("net_dev/command/backup/" + dev.dev_name + "_" + date + ".txt", 'a') as f:
                            f.write(output)

                        data_dic={
                            "title":dev.dev_name + "_" + date + ".txt",
                            "time":now,
                            "ip":ip
                        }
                        DevBackups.objects.create(**data_dic)

                    ip1 = []
                    ip1.append(dev.ip)
                    for ip in ip1:
                        sw = {'device_type': "huawei", 'ip': ip, 'username': dev.username, 'password': dev.password}
                        t = threading.Thread(target=session2, args=(ip, Queue()))
                        t.start()
                        time.sleep(5)
                        result.append(f'{ip}配置备份成功!')

            except Exception as e:
                    pass
        result = '\n'.join(result)

        time.sleep(4)
        return render(request, 'verify_config.html', {"result": result})







